package com.myBlog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.myBlog.constants.RedisConstants;
import com.myBlog.domain.ResponseResult;
import com.myBlog.domain.entity.LoginUser;
import com.myBlog.domain.entity.Menu;
import com.myBlog.domain.entity.User;
import com.myBlog.domain.vo.AdminUserInfoVO;
import com.myBlog.domain.vo.BlogUserLoginVo;
import com.myBlog.domain.vo.RoutersVo;
import com.myBlog.domain.vo.UserInfoVo;
import com.myBlog.enums.AppHttpCodeEnum;
import com.myBlog.exception.SystemException;
import com.myBlog.mapper.UserMapper;
import com.myBlog.service.BlogLoginService;
import com.myBlog.service.LoginService;
import com.myBlog.service.MenuService;
import com.myBlog.service.RoleService;
import com.myBlog.utils.BeanCopyUtils;
import com.myBlog.utils.JwtUtils;
import com.myBlog.utils.RedisCache;
import com.myBlog.utils.SecurityUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

import static com.myBlog.constants.RedisConstants.BLOG_USER_LOGIN;

@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private RedisCache redisCache;

    @Resource
    private MenuService menuService;

    @Resource
    private RoleService roleService;

    /**
     * 用户登录
     *
     * @param user
     * @return
     */
    @Override
    public ResponseResult login(User user) {
        //1.根据username和password封装Authentication对象
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
//        2.AuthenticationManager调用authenticate方法，再调用UserDetailsService的loadUserByUsername方法
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
//        3.判断认证是否通过
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("用户名或密码错误！");
        }
//        4.获取到用户id
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtils.createJWT(userId);

//        5.将用户信息存入缓存
        redisCache.setCacheObject(BLOG_USER_LOGIN + userId, loginUser);

        //6.封装token返回
        HashMap<String, String> map = new HashMap<>();
        map.put("token", jwt);
        return ResponseResult.okResult(map);
    }


    /**
     * 获取用户信息
     *
     * @return
     */
    @Override
    public ResponseResult<AdminUserInfoVO> getInfo() {

        //获取当前登良的用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        //根据用户id查询权限信息
        List<String> perms = menuService.selectPermsUserId(loginUser.getUser().getId());
        //根据用户id查询角色信息
        List<String> roleKeyList = roleService.selectRoleKeyByUser(loginUser.getUser().getId());
        //获取用户信息
        User user = loginUser.getUser();
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);

        //封装数据返回
        AdminUserInfoVO adminUserInfoVO = new AdminUserInfoVO(perms, roleKeyList, userInfoVo);
        return ResponseResult.okResult(adminUserInfoVO);
    }


    /**
     * 获取路由
     *
     * @return
     */
    @Override
    public ResponseResult<RoutersVo> getRouters() {
        //查询Menu结果是tree的形式
        Long userId = SecurityUtils.getUserId();
        List<Menu> menus = menuService.selectRouterMenuTreeByUserId(userId);

        RoutersVo routersVo = new RoutersVo(menus);
        return ResponseResult.okResult(routersVo);
    }

    /**
     * 退出登录
     *
     * @return
     */
    @Override
    public ResponseResult logout() {
        //获取当前登录用户ID
        Long userId = SecurityUtils.getUserId();
        //删除redis中的用户信息
        redisCache.deleteObject(BLOG_USER_LOGIN + userId);
        return ResponseResult.okResult();
    }


}
